昨天我們介紹了函式的基本概念,今天讓我們回過頭來再聊聊變數,以及瞭解變數與函式的關係。
在前面介紹變數的時候,只單純的提了變數的宣告。事實上,變數它是有作用範圍的(Scope)。讓我們來直接看範例:
var x = 3;
function double(num){
var x = 2;
return num * x;
}
console.log(double(5)); //10
console.log(x); //3
在這個範例中,在double()裡面再次定義了變數x,所以當我們執行double(5),經過計算後回傳10,這個地方相信大家都能理解。但如果你是新手的話,可能會不確定為什麼最後一行console.log(x)會印出3,那為什麼不是印出2?
那再讓我改一下這個範例:
function double(num){
var x = 2;
return num * x;
}
console.log(double(5)); //10
console.log(x); //"ReferenceError: x is not defined
改成這樣子,就會發現x變數並沒有被定義。咦?我們不是在double這個function有宣告嗎?這是因為在ES6以前「切分變數有效範圍的最小單位是"function"」。所以函式內定義的變數只屬於這個函式,外面的x跟裡面的x是不一樣的。
我們再改ㄧ下範例:
var x = 2
function double(num){
return num * x;
}
console.log(double(5)); //10
console.log(x); //2
可以發現這次的範例x有順利的找到2,而double function也有順利執行。那這又是為什麼呢?
如果function內部沒有var x,那就會往外一層層找,直到全域物件為止。
所以,可以簡單整理一下,function可以讀取外層已宣告的變數,但外層拿不到裡面宣告的變數。
最後再修改一次範例:
var x = 3;
function double(num){
x = 2;
return num * x;
}
console.log(double(5)); //10
console.log(x); // 2
以為結果是 10 跟 3嗎? 讓我們仔細看一下function中的x並沒有var 宣告。所以,會去外層找有沒有同名的變數,直到最外層,找到了x,然後重新指派2給它,導致在呼叫double(5)之後,印出x會得到2。
以上是var的基本作用範圍介紹,明天讓我們來談談let/const,以及他們的差異吧!
我們明天見!